
#pragma once

#include <ql/config.h>


#ifdef __cplusplus
extern "C"
{
#endif

struct QlStream;

/*typedef unsigned long QlStreamInt;*/
typedef size_t QlStreamInt;

struct QlStreamVtbl
{
    bool (* seek)(struct QlStream * stream, QlStreamInt offset);
    QlStreamInt (* read)(struct QlStream * stream, char * data, QlStreamInt max_size);
    QlStreamInt (* write)(struct QlStream * stream, const char * data, QlStreamInt max_size);
    QlStreamInt (* pos)(struct QlStream * stream);
    /*QlStreamInt (* length)(struct QlStream * stream);*/
    void (* free)(struct QlStream * stream);
};

struct QlStream
{
    const struct QlStreamVtbl * vtbl;
};

/*
 * helper functions
 */

static INLINE bool ql_stream_seek(struct QlStream * stream, QlStreamInt offset)
{
    return stream->vtbl->seek(stream, offset);
}

static INLINE QlStreamInt ql_stream_read(struct QlStream * stream, char * data, QlStreamInt max_size)
{
    return stream->vtbl->read(stream, data, max_size);
}

static INLINE QlStreamInt ql_stream_write(struct QlStream * stream, const char * data, QlStreamInt max_size)
{
    return stream->vtbl->write(stream, data, max_size);
}

static INLINE bool ql_stream_putc(struct QlStream * stream, const char ch)
{
    return 1 == ql_stream_write(stream, &ch, 1);
}

bool ql_stream_puts(struct QlStream * stream, const char * str);

static INLINE QlStreamInt ql_stream_pos(struct QlStream * stream)
{
    return stream->vtbl->pos(stream);
}

static INLINE void ql_stream_free(struct QlStream * stream)
{
    stream->vtbl->free(stream);
}



struct QlStream * ql_create_memory_stream(char ** data,
                                          size_t initial_size,
                                          bool readonly,
                                          void * (* realloc)(void * p, size_t size),
                                          void (* free)(void * p)
                                          );

#ifdef __cplusplus
}
#endif
